package io.jsen.meta.diff.obj;


import io.jsen.meta.diff.field.MetaField;
import io.jsen.meta.diff.obj.special.MetaDelete;
import io.jsen.meta.diff.obj.special.MetaNull;
import io.jsen.meta.diff.support.MetaChangeModifier;
import io.jsen.meta.diff.support.MetaModifier;
import lombok.Getter;

/**
 * O 比较的时候限制是自己
 * <p>
 * S 代表原生类型
 *
 * @author jsen
 * @date 2021/4/6
 */
public abstract class MetaObject<O extends MetaObject<O, S>, S> {
    /**
     * 相关联的diff对象和当前字段的定义
     */
    @Getter
    private final MetaRelation metaRelation;
    /**
     * 当前字段值
     */
    @Getter
    protected S val;
    /**
     * 当前对象索引
     */
    @Getter
    protected String index = "";
    /**
     * 对象属性
     */
    @Getter
    protected int modifier = 0;

    protected MetaObject(MetaField field, S val) {
        field.setTrueClass(val.getClass());
        this.metaRelation = new MetaRelation(field);
        this.val = val;
    }

    @SuppressWarnings("all")
    public MetaObject doDiff(MetaObject obj) {
        this.metaRelation.setRelation(obj);
        if (this instanceof MetaDelete || this instanceof MetaNull) {
            setState(calState(null));
            return this;
        }
        if (obj instanceof MetaNull) {
            if (this instanceof MetaNull) {
                setState(MetaChangeModifier.setNoChange(0));
            } else {
                setState(MetaChangeModifier.setInsert(0));
            }
            return this;
        }
        if (obj instanceof MetaDelete) {
            throw new IllegalArgumentException("不支持diff");
        }
        setState(calState((O) obj));
        return this;
    }

    private void setState(int state) {
        if (!MetaModifier.isCompared(modifier)) {
            modifier = MetaModifier.setMod(modifier, MetaModifier.COMPARED, true);
            modifier = MetaChangeModifier.resetState(modifier, state);
        } else {
            throw new IllegalArgumentException("不能重复diff");
        }
    }

    @Override
    public String toString() {
        String state = MetaChangeModifier.getDesc(modifier);
        if (MetaModifier.anyComplex(modifier)) {
            return state + " (" + metaRelation.toString() + ")";
        } else if (MetaChangeModifier.isNoChange(modifier)) {
            return state + " (" + metaRelation.toString()
                    + ") = " + getVal();
        } else {
            return state + " (" + metaRelation.toString()
                    + ") from " + getMetaRelation().getRelation().getVal()
                    + " to " + getVal();
        }
    }


    /**
     * 计算获取最终状态，不允许在自雷直接设置State
     *
     * @param obj target meta object
     * @return result state
     */
    protected abstract int calState(O obj);
}
